#include "shop_waiter_map.h"

#include <string>
#include <boost/algorithm/string.hpp>

#include "base/logging.h"
#include "base/stop_watch.h"
#include "base/config_reader.h"
#include "database/scoped_connection.h"
#include "database/simple_db_pool.h"
#include "session_thread_manager.h"

#include "im/adapters/session_adapter.h"

namespace imserver {

using apache::thrift::concurrency::Runnable;
class ReloadTask : public Runnable  {
 public:
  ReloadTask(){}
  virtual void run() {
    ShopWaiterMap::Instance().Reload();
    ConfigReader config("../conf/session_service.conf");
    GetTimerManager()->add(boost::shared_ptr<Runnable>(new ReloadTask()), 148 * 1000);
  }
};

ShopWaiterMap::ShopWaiterMap() : db_conn_pool_(NULL) {
  srand(time(NULL));
  ConfigReader config("../conf/session_service.conf");

  db_conn_pool_ = new base::SimpleConnectionPool(config.Get("database", "name").c_str(),
                      config.Get("database", "server_list").c_str(),
                      config.Get("database", "user").c_str(),
                      config.Get("database", "password").c_str());
  GetTimerManager()->add(boost::shared_ptr<Runnable>(new ReloadTask()), 120 * 1000);
}

int ShopWaiterMap::Reload() {
  mysqlpp::ScopedConnection db(*db_conn_pool_);
  if (!db) {
    LOG_ERROR("ShopWaiterMap::Reload failed to get a connection from database-pool.");
    return -1;
  }

  std::map<int64_t, std::vector<int64_t> > waiter_shops;

  mysqlpp::Query query(db->query());
  query << "SELECT shop, waiter FROM shop_waiters";

  try {
    mysqlpp::UseQueryResult ret = query.use();
    if (ret) {
      while(mysqlpp::Row row = ret.fetch_row()) {
        // TODO: 优化性能
        waiter_shops[row["waiter"]].push_back(row["shop"]);

        LOG_DEBUG("ShopWaiterMap::Reload load shop " << row["shop"]
                  << " waiter=" << row["waiter"]);
      }
    }
  } catch (mysqlpp::Exception& e) {
    LOG_ERROR("ShopWaiterMap::Reload " << query.str() << " EXEC ERROR.(" << e.what() << ")");
    return -2;
  }
  LOG_INFO("ShopWaiterMap::Reload ok, waiter_shops.size=" << waiter_shops.size())
  {
    boost::unique_lock<boost::shared_mutex> wlock(waiter_shops_mutex_);
    waiter_shops.swap(waiter_shops_);
  }
  return 0;
}

}

